package net.xxcxcxcx.xc_enhancedmob.skills.basics.individual.rare;

import net.minecraft.entity.mob.MobEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Quaternion;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3f;
import net.xxcxcxcx.xc_enhancedmob.config.skill.SkillConfig;
import net.xxcxcxcx.xc_enhancedmob.entity.SaveFireballEntity;
import net.xxcxcxcx.xc_enhancedmob.packet.CustomParticlePacket;
import net.xxcxcxcx.xc_enhancedmob.render.particle.summon.magic.circle.BaseAttackParticle;
import net.xxcxcxcx.xc_enhancedmob.render.particle.summon.magic.circle.BaseSummonMagicCircleParticle;
import net.xxcxcxcx.xc_enhancedmob.skills.BaseSkill;
import net.xxcxcxcx.xc_enhancedmob.skills.SkillRarity;

import java.util.Random;

public class MeteorSkill extends BaseSkill {

    Vec3d target = null;

    public MeteorSkill(int level) {
        super(level);
    }

    public MeteorSkill(NbtCompound nbtCompound) {
        super(nbtCompound);
        readbyNbtCompound(nbtCompound);
    }

    public MeteorSkill() {
    }

    @Override
    public SkillConfig getDefaultConfig() {
        SkillConfig skillConfig = super.getDefaultConfig();
        skillConfig.setPreparationtime(40);
        skillConfig.setCooldown(200);
        skillConfig.setInsideCooldown(10);
        skillConfig.setInsideMaxUseCount(10);
        skillConfig.setMessage(getConfigMessage(skillConfig));
        return skillConfig;
    }

    @Override
    public String getConfigMessage(SkillConfig skillConfig) {
        if (skillConfig == null) return super.getConfigMessage(null);
        return String.format("流星技能，从天上召唤火球进行攻击,会有瞄准提示。准备时间 %d tick,重复次数 %d tick,内置冷却时间 %d tick,冷却时间 %d tick",
                skillConfig.getPreparationtime(), skillConfig.getInsideMaxUseCount(), skillConfig.getInsideCooldown(), skillConfig.getCooldown());
    }

    @Override
    public NbtCompound getNbtCompound() {
        NbtCompound nbtCompound = super.getNbtCompound();
        if (target != null) {
            NbtCompound tar = new NbtCompound();
            tar.putDouble("x", target.x);
            tar.putDouble("y", target.y);
            tar.putDouble("z", target.z);
            nbtCompound.put("target", tar);
        }
        return nbtCompound;
    }

    //通过nbt新建
    @Override
    public void readbyNbtCompound(NbtCompound nbtCompound) {
        super.readbyNbtCompound(nbtCompound);
        if (nbtCompound.contains("target")) {
            NbtCompound tar = nbtCompound.getCompound("target");
            double x = tar.getDouble("x");
            double y = tar.getDouble("y");
            double z = tar.getDouble("z");
            target = new Vec3d(x, y, z);
        }
    }

    public SkillRarity getSkillRarity() {
        return SkillRarity.Rare;
    }

    @Override
    public boolean canUseAbility(MobEntity mobEntity) {
        return (getSkilltime() < mobEntity.world.getTime());
    }

    public int getshoutcount() {
        return 5;
    }

    @Override
    public boolean onAbilityUse(MobEntity mobEntity) {
        if (canUseAbility(mobEntity)) {
            if (target != null) {
                Random random = new Random();
                double f = target.getX() - (mobEntity.getX());
                double g = target.getY() - (3 + mobEntity.getBodyY(1.5));
                double h = target.getZ() - (mobEntity.getZ());
                SaveFireballEntity fireballEntity = new SaveFireballEntity(mobEntity.world, mobEntity, f, g, h, null);
                fireballEntity.explosionPower = getSkillLevel();
                fireballEntity.setPosition(mobEntity.getX(), mobEntity.getBodyY(1.5) + 3, fireballEntity.getZ());
                Vec3d vec3d1 = fireballEntity.getPos().relativize(target).normalize();
                Vec3d vec3d2 = new Vec3d(0, 1, 0);
                Vec3d vec3d3 = vec3d1.crossProduct(vec3d2).normalize();
                float angle = (float) Math.acos((vec3d1.x * vec3d2.x + vec3d1.y * vec3d2.y + vec3d1.z * vec3d2.z) / (vec3d1.length() * vec3d2.length()));
                Quaternion quaternion = new Quaternion(new Vec3f(vec3d3), -angle, false);
                Vec3f vec3f = new Vec3f(random.nextFloat() * (float) Math.sqrt(getshoutcount()) - (float) Math.sqrt(getshoutcount()) / 2.0f, 0, random.nextFloat() * (float) Math.sqrt(getshoutcount()) - (float) Math.sqrt(getshoutcount()) / 2.0f);
                vec3f.rotate(quaternion);
                fireballEntity.setPos(fireballEntity.getX() + vec3f.getX(), fireballEntity.getY() + vec3f.getY(), fireballEntity.getZ() + vec3f.getZ());
                mobEntity.world.spawnEntity(fireballEntity);

                if (getSkillInsideUsecount() == 0 && mobEntity.world instanceof ServerWorld serverWorld) {
                    CustomParticlePacket.Updata(new BaseAttackParticle(0, new Vec3d(mobEntity.getX(), mobEntity.getBodyY(1.5) + 3, mobEntity.getZ()), 100, target, 0.1f), new BlockPos(target), serverWorld);
                }
                setSkillInsideUsecount(getSkillInsideUsecount() + 1);
                if (getSkillInsideUsecount() < getInsideMaxUseCount()) {
                    setSkilltime(mobEntity.world.getTime() + getInsideCooldown());
                } else {
                    target = null;
                    setSkillInsideUsecount(0);
                    setwhetherPreparationTime(false);
                    setSkilltime(mobEntity.world.getTime() + getCooldown());
                }
            } else if (mobEntity.getTarget() != null) {
                if (!getwhetherPreparationTime()) {
                    target = new Vec3d(mobEntity.getTarget().getX(), mobEntity.getTarget().getBodyY(0.15), mobEntity.getTarget().getZ());
                    setSkilltime(mobEntity.world.getTime() + getPreparationTime());
                    setwhetherPreparationTime(true);
                    if (mobEntity.world instanceof ServerWorld serverWorld)
                        CustomParticlePacket.Updata(new BaseSummonMagicCircleParticle(0, new Vec3d(target.getX(), target.getY() + 0.1f, target.getZ()), 100), new BlockPos(target), serverWorld);
                } else {
                    target = null;
                    setSkillInsideUsecount(0);
                    setwhetherPreparationTime(false);
                    setSkilltime(mobEntity.world.getTime() + getCooldown());
                }
            }
        }
        return true;
    }
}
